﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Universum.Model.Domain;
using Universum.Model.Services.Indexing;
using Db4objects.Db4o.Linq;
namespace Universum.Infrastructure.Persistence
{
	/// <summary>
	/// This class providers the implementation for the
	/// <c href="Universum.Infrastructure.Persistence.IRepository">IRepository</c>
	/// interface
	/// </summary>
	public class Db4oRepository : IRepository
	{
		private readonly IDb4oUnitOfWork _unitOfWork;
		
		public Db4oRepository(IDb4oUnitOfWork unitOfWork)
		{
			_unitOfWork = unitOfWork;
			
		}
		#region IRepository Members

		public void SaveOrUpdate<ENTITY>(ENTITY entity) where ENTITY : DomainEntity
		{
			_unitOfWork.Client.Store(entity);
			_unitOfWork.Commit();
		}

		public ENTITY Load<ENTITY>(Guid id) where ENTITY : DomainEntity
		{
			var result =
				_unitOfWork.Client.Cast<ENTITY>()
				.Where(e => e.ID == id)
				.FirstOrDefault();
			_unitOfWork.Commit();
			return result;
				
		}

		public IQueryable<ENTITY> Query<ENTITY>() where ENTITY : DomainEntity
		{
			var result = _unitOfWork.Client.Cast<ENTITY>().AsQueryable();
			_unitOfWork.Commit();
			return result;
		}

		public IQueryable<ENTITY> Query<ENTITY>(IDomainQuery<ENTITY> whereQuery) where ENTITY : DomainEntity
		{

			var result =  _unitOfWork.Client.Cast<ENTITY>().AsQueryable().Where(
				whereQuery.Expression);
			_unitOfWork.Commit();
			return result;
			
		}

		public void Remove<ENTITY>(ENTITY entity) where ENTITY : DomainEntity
		{
			_unitOfWork.Client.Delete(entity);
			_unitOfWork.Commit();
			
		}
	
		public IQueryable<ENTITY> QueryPaged<ENTITY>(int pageIndex, int pageSize) where ENTITY : DomainEntity
		{
			int entitiesToSkip = pageIndex * pageSize;
			var result = _unitOfWork.Client.Cast<ENTITY>()
				.AsQueryable()
				.Skip(entitiesToSkip)
				.Take(pageSize);
			_unitOfWork.Commit();
			return result;
		
		}

		public IQueryable<ENTITY> QueryPaged<ENTITY>(IDomainQuery<ENTITY> whereQuery, int pageIndex, int pageSize) where ENTITY : DomainEntity
		{
			int entitiesToSkip = pageIndex * pageSize;
			var result =  _unitOfWork.Client.Cast<ENTITY>().AsQueryable()
				.Where(whereQuery.Expression)
				.Skip(entitiesToSkip)
				.Take(pageSize);

			_unitOfWork.Commit();
			return result;
			
		}

		#endregion
	}
}
